package com.nixsolutions.dao;

import com.nixsolutions.bean.User;
import java.util.List;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;

/**
 *
 * @author yakimovich
 */
public class HibernateUserDao implements UserDao {

    /**
     * Create logger.
     */
    private static org.apache.commons.logging.Log logger = LogFactory.getLog(HibernateUserDao.class);
    
    @Autowired
    private SessionFactory sessionFactory;

    public HibernateUserDao() {
    }
    
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    @Override
    public void create(User user) {
        if (user == null) {
            throw new NullPointerException();
        }

        Session session = null;
        Transaction transaction = null;

        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            session.save(user);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }

    @Override
    public void update(User user) {

        if (user == null) {
            throw new NullPointerException();
        }

        Session session = null;
        Transaction transaction = null;

        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            session.update(user);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }

    @Override
    public void remove(User user) {

        if (user == null) {
            throw new NullPointerException();
        }

        Session session = null;
        Transaction transaction = null;
        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            session.delete(user);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }

    @Override
    public List<User> findAll() {
        List<User> users = null;

        Session session = null;
        Transaction transaction = null;


        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            Criteria criteria = session.createCriteria(User.class);
            users = criteria.list();
            
            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
        return users;
    }

    @Override
    public User findByLogin(String login) {

        if (login == null) {
            throw new NullPointerException();
        }
        User user = null;
        Session session = null;
        Transaction transaction = null;
        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            Criteria criteria = session.createCriteria(User.class);
            criteria.add(Restrictions.eq("login", login));
            List<User> users = criteria.list();
            if (users.isEmpty()) {
                throw new IllegalArgumentException();
            }
            user = users.get(0);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
        return user;
    }

    @Override
    public User findByEmail(String email) {

        if (email == null) {
            throw new NullPointerException();
        }
        User user = null;
        Session session = null;
        Transaction transaction = null;
        try {
            session = sessionFactory.openSession();
            transaction = session.getTransaction();
            transaction.begin();

            Criteria criteria = session.createCriteria(User.class);
            criteria.add(Restrictions.eq("email", email));
            List<User> users = criteria.list();
            if (users.isEmpty()) {
                throw new IllegalArgumentException();
            }
            user = users.get(0);

            transaction.commit();
        } catch (Exception e) {
            logger.error(this, e);
            transaction.rollback();
            throw new RuntimeException(e);
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
        return user;
    }
}
